#ifndef __MISC_H__
#define __MISC_H__

#include <rte_atomic.h>
#include <rte_branch_prediction.h>
#include <rte_common.h>
#include <rte_cycles.h>
#include <rte_debug.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
#include <rte_ether.h>
#include <rte_interrupts.h>
#include <rte_launch.h>
#include <rte_lcore.h>
#include <rte_log.h>
#include <rte_mbuf.h>
#include <rte_memory.h>
#include <rte_mempool.h>
#include <rte_memzone.h>
#include <rte_malloc.h>
#include <rte_ethdev.h>
#include <rte_pci.h>
#include <rte_per_lcore.h>
#include <rte_ring.h>
#include <rte_string_fns.h>
#include <stdio.h>
#include <syslog.h>
#include <endian.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <unistd.h>
#include <zlib.h>
#include "mbedtls/config.h"
#include "mbedtls/platform.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "mbedtls/timing.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <signal.h>
#if defined(MBEDTLS_SSL_CACHE_C)
#include "mbedtls/ssl_cache.h"
#endif

#if defined(MBEDTLS_SSL_TICKET_C)
#include "mbedtls/ssl_ticket.h"
#endif

#if defined(MBEDTLS_SSL_COOKIE_C)
#include "mbedtls/ssl_cookie.h"
#endif

#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#include "mbedtls/memory_buffer_alloc.h"
#endif
#include "list.h"
#include "log.h"

#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef likely
#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)
#endif

#define FAKE_PKG_POOL_SIZE 1024
#define TUPLE_CT_FLAG_CLIENT_FIN                0x00000004
//#define TUPLE_CT_FLAG_CLIENT_FIN_ACKED          0x00000008
#define TUPLE_CT_FLAG_FILTER_HIT                0x00000010
#define TUPLE_CT_FLAG_HTTP_CHUNKED              0x00000040
#define TUPLE_CT_FLAG_HTTP_DEFLATE              0x00000080
#define TUPLE_CT_FLAG_HTTP_GZIP                 0x00000100
#define TUPLE_CT_FLAG_HTTP_IMAGE                0x00000200
#define TUPLE_CT_FLAG_HTTP_REFERER              0x00000400
#define TUPLE_CT_FLAG_HTTP_REPLY_0D0A0D0A       0x00000800
#define TUPLE_CT_FLAG_HTTP_TEXT                 0x00001000
#define TUPLE_CT_FLAG_NOFILTER_HIT              0x00002000
#define TUPLE_CT_FLAG_RECORD_ACC                0x00004000
#define TUPLE_CT_FLAG_SERVER_ACCESS_OUTSIDE     0x00008000
#define TUPLE_CT_FLAG_SERVER_FIN                0x00010000
//#define TUPLE_CT_FLAG_SERVER_FIN_ACKED          0x00020000
#define TUPLE_CT_FLAG_MATCH_BINGDU_POSTFIX      0x00040000
#define TUPLE_CT_FLAG_SSL_STOP_SEND             0x00100000
#define TUPLE_CT_FLAG_SSL_INIT                  0x00200000
#define GET_PACKINF(m)          ((struct packinf *)(m+1))
#define IS_IPV6(m)              (((struct packinf *)(m+1))->is_ipv6)
#define APP_DATA_LEN(m)         (GET_PACKINF(m)->high_offset)
#define DATA_SIZE               0x100
#define L3_OFFSET(m)            (GET_PACKINF(m)->l3_offset)
#define L4PROTOCOL_TCP          1
#define L4PROTOCOL_UDP          2
#define L4_OFFSET(m)            (GET_PACKINF(m)->l4_offset)
#define MAC_STR_BUF_SIZE        18
#define MASK_DOMAIN             1
#define MASK_DST_IPV4           16
#define MASK_DST_PORT           64
#define MASK_KEYWORD            4
#define MASK_PROTOCOL           128
#define MASK_SRC_IPV4           8
#define MASK_SRC_PORT           32
#define MASK_URL                2
#define MAX_PORT                8
#define MAX_QUEUE               8
#define MAX_OUTPUT              8
#define PACK_DIR(m)             (GET_PACKINF(m)->pack_dir)
#define port_count rte_eth_dev_count()
typedef uint8_t u8;

struct packinf {
    char is_come_from_server;
    char is_ipv6;
    int pack_dir;
    int high_offset;
    int l3_offset;
    int l4_offset;
    struct rte_mbuf *tcp_sort_next;
    struct rte_mbuf *sended_packet_next;
    struct rte_mbuf *unsend_packet_next;
    struct rte_mbuf *recv_packet_next;
    uint32_t app_data_len;
    uint32_t seq;
    uint8_t l4_protocol;
    uint8_t queue;
    uint8_t send_to_client_port;
    uint8_t send_to_server_port;
};

typedef	uint32_t tcp_seq;
struct tcphdr
  {
    __extension__ union
    {
      struct
      {
	uint16_t th_sport;	/* source port */
	uint16_t th_dport;	/* destination port */
	tcp_seq th_seq;		/* sequence number */
	tcp_seq th_ack;		/* acknowledgement number */
# if __BYTE_ORDER == __LITTLE_ENDIAN
	uint8_t th_x2:4;	/* (unused) */
	uint8_t th_off:4;	/* data offset */
# endif
# if __BYTE_ORDER == __BIG_ENDIAN
	uint8_t th_off:4;	/* data offset */
	uint8_t th_x2:4;	/* (unused) */
# endif
	uint8_t th_flags;
# define TH_FIN	0x01
# define TH_SYN	0x02
# define TH_RST	0x04
# define TH_PUSH	0x08
# define TH_ACK	0x10
# define TH_URG	0x20
	uint16_t th_win;	/* window */
	uint16_t th_sum;	/* checksum */
	uint16_t th_urp;	/* urgent pointer */
      };
      struct
      {
	uint16_t source;
	uint16_t dest;
	uint32_t seq;
	uint32_t ack_seq;
# if __BYTE_ORDER == __LITTLE_ENDIAN
	uint16_t res1:4;
	uint16_t doff:4;
	uint16_t fin:1;
	uint16_t syn:1;
	uint16_t rst:1;
	uint16_t psh:1;
	uint16_t ack:1;
	uint16_t urg:1;
	uint16_t res2:2;
# elif __BYTE_ORDER == __BIG_ENDIAN
	uint16_t doff:4;
	uint16_t res1:4;
	uint16_t res2:2;
	uint16_t urg:1;
	uint16_t ack:1;
	uint16_t psh:1;
	uint16_t rst:1;
	uint16_t syn:1;
	uint16_t fin:1;
# else
#  error "Adjust your <bits/endian.h> defines"
# endif
	uint16_t window;
	uint16_t check;
	uint16_t urg_ptr;
      };
    };
};

typedef struct {
    int sended_packet_count[2];
    int unsend_packet_count[2];
    mbedtls_ssl_config conf[2];
    mbedtls_ssl_context ssl[2];
    size_t recv_len[2];
    size_t send_len[2];
    struct rte_mbuf *recved_packet_last[2];
    struct rte_mbuf *recved_packets[2];
    struct rte_mbuf *sended_packet_last[2];
    struct rte_mbuf *sended_packets[2];
    struct rte_mbuf *unsend_packet_last[2];
    struct rte_mbuf *unsend_packets[2];
    uint32_t last_deal_pkg_seq_add_len[2];
    uint32_t sended_unack_len[2];
    uint32_t unsend_len[2];
    uint8_t recv_buf[2][1460*12];
    uint8_t send_buf[2][1460*12];
    unsigned flag;
} SSL_CONTEXT;

typedef struct tuple {
    SSL_CONTEXT *ssl_context;
    struct my_hlist_node node;
    struct my_list_head list_node;
    struct rte_mbuf *tcp_sort_cache[2];
    time_t create_ts;
    time_t ts;
    uint16_t dstport;
    uint16_t service;
    uint16_t srcport;
    uint32_t dstip[4];
    uint32_t flag;
    uint32_t packet_count;
    uint32_t srcip[4];
    uint32_t tcp_sort_cache_count[2];
    uint32_t wait_seq[2];
    uint8_t dstmac[6];
    uint8_t protocol;
    uint8_t srcmac[6];
    uint8_t client_port;
    uint8_t server_port;
    unsigned to_client_my_seq;
    unsigned to_server_my_seq;
} tuple_t;

extern struct if_stats *if_stats;
extern time_t g_start_time;
extern time_t g_time;

static inline unsigned hash31(const void *str, int len)
{
    unsigned hash = 0;
    const unsigned char *p = str;
    while (--len >=0) hash = hash*31 + p[len];
    return hash;
}

static inline uint64_t hash31_64(const void *str, int len)
{
    uint64_t hash = 0;
    const unsigned char *p = str;
    while (--len >=0) hash = hash*31 + p[len];
    return hash;
}

#endif
